package yxy.apple.util;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;

public class RandomUtility {
	private static Random random = new Random(System.currentTimeMillis());

	public static byte[] nextBytes(int length) {
		byte[] buffer = new byte[length];
		random.nextBytes(buffer);
		return buffer;
	}

	/**
	 * 
	 * @param minimum 最小可能取值（包括）
	 * @param maximum 最大可能取值（不包括）
	 * @return
	 */
	public static boolean nextBoolean() {
		return random.nextBoolean();
	}

	/**
	 * 
	 * @param minimum 最小可能取值（包括）
	 * @param maximum 最大可能取值（不包括）
	 * @return
	 */
	public static int nextInt(int minimum, int maximum) {
		int limit = maximum - minimum;
		return minimum + random.nextInt(limit);
	}

	/**
	 * 
	 * @param minimum 最小可能取值（包括）
	 * @param maximum 最大可能取值（不包括）
	 * @return
	 */
	public static long nextLong(long minimum, long maximum) {
		long limit = maximum - minimum;
		return minimum + (long) (random.nextDouble() * limit);
	}

	/**
	 * 
	 * @param minimum 最小可能取值（包括）
	 * @param maximum 最大可能取值（不包括）
	 * @return
	 */
	public static double nextDouble(double minimum, double maximum) {
		double limit = maximum - minimum;
		return minimum + random.nextDouble() * limit;
	}

	/**
	 * 
	 * @param minimum 最小可能取值（包括）
	 * @param maximum 最大可能取值（不包括）
	 * @return
	 */
	public static double nextFloat(float minimum, float maximum) {
		float limit = maximum - minimum;
		return minimum + random.nextFloat() * limit;
	}

	/** 万分比概率随机取值 范围(0,10000] */
	public static int ppm() {
		return nextInt(0, 10000);
	}

	/**
	 * 按标准正态分布取一个随机值
	 * 
	 * @return
	 */
	public static double nextStandardNormalDistribution() {
		return random.nextGaussian();
	}

	/**
	 * 按正态分布 N(μ, σ) 取一个随机值
	 * 
	 * @param μ 均值
	 * @param σ 标准差
	 * @return
	 */
	public static double nextNormalDistribution(double μ, double σ) {
		// 根据标准正态分布转换，可以证明结果可信
		double value = nextStandardNormalDistribution();
		return σ * value + μ;
	}

	/** 按权重随机一个list里的对象 */
	public static <T extends Weight> T randomWeight(List<T> list) {
		int total = 0;
		for (T t : list) {
			total += t.getWeight();
		}
		int rnd = nextInt(0, total);
		for (T t : list) {
			rnd -= t.getWeight();
			if (rnd < 0) {
				return t;
			}
		}
		return list.get(0);
	}

	/** 按权重取list里的num个不重复对象 递归方式 */
	public static <T extends Weight> List<T> randomWeight(List<T> list, List<T> result, int num) {
		if (num >= list.size()) {
			return list;
		}
		if (result == null) {
			result = new ArrayList<>();
		}
		if (num <= 0) {
			return result;
		}
		int total = 0;
		for (T t : list) {
			total += t.getWeight();
		}
		int rnd = nextInt(0, total);
		for (T t : list) {
			rnd -= t.getWeight();
			if (rnd < 0) {
				result.add(t);
				list.remove(t);
				return randomWeight(list, result, num - 1);
			}
		}
		return result;
	}

	/** 用于随机的权重对象 */
	static public interface Weight {
		int getWeight();
	}
}
